package zdc.media {
import app.event.AppEvent;

import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Stage;
import flash.events.AsyncErrorEvent;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.events.NetStatusEvent;
import flash.events.StageVideoAvailabilityEvent;
import flash.events.StageVideoEvent;
import flash.geom.Rectangle;
import flash.media.StageVideo;
import flash.media.StageVideoAvailability;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;

import partition.interfaces.IPartition;
import partition.ui.Partition;

import zdc.Util;

/**
 *
 * @author Metal Slime
 */
public class VideoAdapter extends EventDispatcher {
    public static const VIDEO_ADAPTER_PLAY_END:String = "VIDEO_ADAPTER_PLAY_END";
    public static const VIDEO_ADAPTER_PLAY_START:String = "VIDEO_ADAPTER_PLAY_START";

    private var _vid:Video;
    private var _sv:StageVideo;
    //private var _sv:Object;
    private var _nc:NetConnection;
    private var _ns:NetStream;
    private var _file:String;
    private var _accel:Boolean = false;
    private var _playing:Boolean = false;

    private var _dio:DisplayObjectContainer;
    private var _stage:Stage;
    private var _rect:Rectangle;
    private var _autoPlay:Boolean = false;

    private var _endFun:Function;
    private var _startFun:Function;

    private var _availableNum:int = 0;

    private var _visible:Boolean = true;


    private var _forceSoft:Boolean = false;

    public function VideoAdapter(dio:DisplayObjectContainer, filePath:String, autoPlay:Boolean = false, rect:Rectangle = null, endFun:Function = null, forceSoft:Boolean = true) {
        _dio = dio;
        _stage = dio.stage;
        _rect = rect || new Rectangle(0, 0, _stage.stageWidth, _stage.stageHeight);
        _endFun = endFun;
        _file = filePath;
        _autoPlay = autoPlay;
        _forceSoft = forceSoft;

        initConnect();

        _stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, onVideoAvail);
        _stage.addEventListener(Event.RESIZE, onResize);

    }

    private function initConnect():void {
        if (_nc) {
            _nc.close();
        }
        if (_ns) {
            _ns.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsynErr);
            _ns.removeEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
            _ns.close();
        }
        _nc = new NetConnection();
        _nc.connect(null);
        _ns = new NetStream(_nc);
        _ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsynErr);
        _ns.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
        _ns.client = this;
    }

    private function onResize(e:Event):void {

    }

    private function resize():void {
        if (_accel && _sv) {
            _sv.viewPort = _rect;
        }
        else if (!_accel && _vid) {
        }
    }

    protected function onNetStatus(e:NetStatusEvent):void {
        switch (e.info.code) {
            case "NetStream.Play.Stop":
                _endFun && _endFun();
                dispatchEvent(new Event(VIDEO_ADAPTER_PLAY_END));
                _endFun = null;
                _playing = false;
                break;
            case "NetStream.Play.Start":
                //trace("NetStream.Play.Start", _ns.time, _file);
                dispatchEvent(new Event(VIDEO_ADAPTER_PLAY_START));
                _startFun && _startFun();
                _startFun = null;
                _playing = true;
                break;
        }
    }

    public function onPlayStatus(info:Object):void {
        //trace("onPlayStatus", info.code);
    }

    protected function onAsynErr(e:AsyncErrorEvent):void {
    }

    public function onXMPData(info:Object):void {

    }

    private function onVideoAvail(e:StageVideoAvailabilityEvent):void {
        if (e.availability == StageVideoAvailability.AVAILABLE) {
            _accel = true;
        }
        if (!_sv && _accel && !_forceSoft) {
            var vids:Vector.<StageVideo> = _stage.stageVideos;
            _availableNum = vids.length;
            _sv = vids[0];
            _sv.addEventListener(StageVideoEvent.RENDER_STATE, onRenderState);
            if (_vid) {
                _dio.removeChild(_vid);
            }

            if (!_playing) {
                _sv.attachNetStream(_ns);
                if (_autoPlay) {
                    _ns.play(_file);
                    _playing = true;
                }
            }
        }
        //else if (!_accel && !_vid) {
        else if (!_vid) {
            if (!_vid) {
                _vid = new Video(_rect.width, _rect.height);
                _dio.addChild(_vid);

            }
            if (!_playing) {
                _vid.attachNetStream(_ns);
                if (_autoPlay) {
                    _ns.play(_file);
                    _playing = true;
                }
            }
        }
    }

    private function onRenderState(e:StageVideoEvent):void {
        resize();
    }

    public function play():void {			//trace(_sv, _ns, !_playing, _vid, _autoPlay);
        if (!_playing && _sv) {
            _sv.attachNetStream(_ns);
            _ns.play(_file);
            _playing = true;
        }
        else if (_vid && !_playing) {
            _vid.attachNetStream(_ns);
            _ns.play(_file);
            _playing = true;
        }
        else if ((!_vid) || (!_sv)) {
            autoPlay = true;
        }
    }

    public function playFile(path:String):void {
        //initConnect();
        if (_sv) {
            _sv.attachNetStream(_ns);
        }
        else if (_vid) {
            _vid.clear();
            _vid.attachNetStream(_ns);
        }
        _ns.play(path);
        _file = path;
        _playing = true;
    }

    public function stop(over:Boolean = false):void {
        if (_sv) {
            _ns.pause();
            //_ns.close();
        }
        else if (_vid) {
            _ns.pause();
            //_ns.close();
        }
        _playing = false;
        over && dispose();
    }

    public function get visible():Boolean {
        return _visible;
    }

    public function set visible(value:Boolean):void {
        if (!value) {
            if (_vid) {
                _vid.visible = false
            }
            if (_sv) {
                _sv.attachNetStream(null);
            }
        }
        else {
            if (_vid) {
                _vid.visible = true;
            }
            if (_sv) {
                !_visible && _sv.attachNetStream(_ns);
            }
        }
        _visible = value;
    }

    public function dispose():void {
        if (_nc) {
            _nc.close();
            _nc = null;
        }
        if (_ns) {
            _ns.close();
            _ns.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsynErr);
            _ns.removeEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
            _ns = null;
        }
        if (_sv) {
            _sv.attachNetStream(null);
            _sv.removeEventListener(StageVideoEvent.RENDER_STATE, onRenderState);
            _sv = null;
        }
        else if (_vid) {
            _vid.attachNetStream(null);
            Util.rmChild(_vid);
            _vid = null;
        }

        _stage.removeEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, onVideoAvail);
        _stage.removeEventListener(Event.RESIZE, onResize);
        _playing = false;
    }

    public function onMetaData(evt:Object):void {

    }

    /**
     * 获取可以用的视频对象
     */
    public function get video():Object {
        return _accel ? _sv : _vid;
    }

    /**
     * 可用的数量
     */
    public function get availableNum():int {
        return _availableNum;
    }

    /**
     * 是否可以硬件加速
     */
    public function get accel():Boolean {
        return _accel;
    }

    public function get autoPlay():Boolean {
        return _autoPlay;
    }

    public function set autoPlay(value:Boolean):void {
        _autoPlay = value;
    }

    public function get file():String {
        return _file;
    }

    public function set file(value:String):void {
        _file = value;
    }

    public function get endFun():Function {
        return _endFun;
    }

    public function set endFun(value:Function):void {
        _endFun = value;
    }

    public function get startFun():Function {
        return _startFun;
    }

    public function set startFun(value:Function):void {
        _startFun = value;
    }

    public function get forceSoft():Boolean {
        return _forceSoft;
    }

    public function set forceSoft(value:Boolean):void {
        _forceSoft = value;
    }

}

}